package com.yanqu.road.server.manger.activity.apprentice;

import com.yanqu.road.dao.impl.activity.apprentice.ApprenticeUserPatronsTalentDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.apprentice.ApprenticeTalentData;
import com.yanqu.road.entity.activity.apprentice.config.*;
import com.yanqu.road.entity.activity.apprentice.data.ApprenticeUserPatronsTalentData;
import com.yanqu.road.entity.activity.apprentice.enums.ApprenticeProjectSortEnum;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eOccupationType;
import com.yanqu.road.logic.bussiness.DaoHelper;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.thread.ThreadTaskManger;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.apprentice.ApprenticeModule;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.config.MallMgr;
import com.yanqu.road.server.manger.config.PatronsMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ApprenticeMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(ApprenticeMgr.class.getName());

    /**
     * 配置MAP
     */
    private static Map<Integer, ApprenticeConfig> configMap = new ConcurrentHashMap<>();

    /**
     * 线程池
     */
    private static ThreadTaskManger apprenticeThreadPool;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        //初始化线程池，开1个线程池，线程数量2个
        if(null == apprenticeThreadPool) {
            apprenticeThreadPool = new ThreadTaskManger(1, "apprenticeThreadPool", 2);
        }
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    /**
     * 获取配置MAP
     * @return
     */
    public static Map<Integer, ApprenticeConfig> getConfigMap() {
        return configMap;
    }

    /**
     * 获取活动配置
     * @param activityId
     * @return
     */
    public static ApprenticeConfig getConfig(int activityId) {
        return configMap.get(activityId);
    }

    /**
     * 加载活动配置
     */
    public static void reloadActivityData() {
        logger.info("reload apprentice Activity start");
        //获取活动
        List<ActivityInfo> activityList = NormalActivityMgr.getOpenActivityInfoList(eActivityType.Apprentice.getValue());
        Map<Integer, ApprenticeConfig> newActivityConfigMap = new ConcurrentHashMap<>();
        for (ActivityInfo activityInfo : activityList) {
            //获取config
            Map<String, ActivityConfig> configMap = NormalActivityMgr.getActivityConfigMap(activityInfo.getActivityId());
            //等级配置
            Map<Integer, ApprenticeLevelConfig> levelConfigMap = DaoHelper.getGenericConfigDaoImpl().getGenericConfigMap(activityInfo.getActivityId(), ApprenticeLevelConfig.class);
            //项目配置
            Map<Integer, ApprenticeProjectConfig> projectConfigMap = DaoHelper.getGenericConfigDaoImpl().getGenericConfigMap(activityInfo.getActivityId(), ApprenticeProjectConfig.class);
            //小考模版配置
            Map<Integer, ApprenticeModelConfig> modelConfigMap = DaoHelper.getGenericConfigDaoImpl().getGenericConfigMap(activityInfo.getActivityId(), ApprenticeModelConfig.class);
            //保底配置
            Map<Integer, ApprenticeHelpConfig> helpConfigMap = DaoHelper.getGenericConfigDaoImpl().getGenericConfigMap(activityInfo.getActivityId(), ApprenticeHelpConfig.class);
            //实例化活动配置
            ApprenticeConfig ApprenticeConfig = new ApprenticeConfig(activityInfo, configMap, levelConfigMap, projectConfigMap, modelConfigMap, helpConfigMap);
            newActivityConfigMap.put(activityInfo.getActivityId(), ApprenticeConfig);
        }
        configMap = newActivityConfigMap;
        //同步一下在线玩家
        List<GamePlayer> playerList = GamePlayerMgr.getAllOnlinePlayer();
        for (GamePlayer gamePlayer : playerList) {
            gamePlayer.getModule(ApprenticeModule.class).syncConfig();
        }
        logger.info("reload apprentice Activity end");
    }

    /**
     * 跨服返回-更新玩家天资
     * @param activityId
     * @param userId
     * @param talentType
     * @param talentValue
     */
    public static void changeUserTalentFromCross(int activityId, long userId, int talentType, long talentValue, long allTalentValue) {
        //注入异步task
        apprenticeThreadPool.addTask(0, new ApprenticeSyncAddTalentThreadTask(activityId, userId, talentType, talentValue, allTalentValue));
    }

    /**
     * 跨服返回-更新玩家天资
     * @param activityId
     * @param userId
     * @param talentType
     * @param talentValue
     */
    public static void syncChangeUserTalent(int activityId, long userId, int talentType, long talentValue, long allTalentValue) {
        //获取活动配置
        ApprenticeConfig config = getConfig(activityId);
        if (config == null) {
            logger.error("爱徒养成-变更玩家天资跨服返回-失败-活动配置未找到，{}, {}, {}, {}", activityId, userId, talentType, talentValue);
            return;
        }
        int mallShopType = config.getSHOW_PARTON_GET();
//        //获取玩家
//        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
//        if (gamePlayer != null) {
//            gamePlayer.getModule(ApprenticeModule.class).addPatronsTalent(mallShopType, talentType, talentValue);
//            //榜单，成就
//            gamePlayer.getModule(ApprenticeModule.class).scoreChange(activityId, allTalentValue);
//        } else {
//            //玩家不存在，更新数据库
//            ApprenticeUserPatronsTalentDataDaoImpl dao = new ApprenticeUserPatronsTalentDataDaoImpl();
//            ApprenticeUserPatronsTalentData data = dao.getUserPatronsTalentByMallShopType(userId, mallShopType);
//            if (data != null) {
//                data.addTalent(talentType, talentValue);
//                dao.update(data);
//            }
//        }
        //获取玩家
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
        if (gamePlayer == null) {
            //加载一下玩家数据，触发该情况的频率不高，可以这样写一下
            gamePlayer = GamePlayerMgr.getPlayer(userId);
        }
        if (gamePlayer == null) {
            return;
        }
        //加天资
        gamePlayer.getModule(ApprenticeModule.class).addPatronsTalent(mallShopType, talentType, talentValue);
        //榜单，成就
        gamePlayer.getModule(ApprenticeModule.class).scoreChange(activityId, allTalentValue);
    }


    /**
     * 获取玩家门客资质加成MAP
     * @param userId
     * @return K:门客ID,V:资质值
     */
    public static Map<Integer, Long> getPatronsAddQualification(long userId) {
        //获取玩家
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
        Map<Integer, ApprenticeUserPatronsTalentData> userPatronsTalentDataMap;
        if (gamePlayer != null) {
            userPatronsTalentDataMap = gamePlayer.getModule(ApprenticeModule.class).getUserPatronsTalentDataMap();
        } else {
            //读库
            userPatronsTalentDataMap = new ApprenticeUserPatronsTalentDataDaoImpl().getApprenticeUserPatronsTalentDataMap(userId);
        }
        Map<Integer, Long> result = new HashMap<>();
        for (ApprenticeUserPatronsTalentData data : userPatronsTalentDataMap.values()) {
            for (int patronsId : data.getPatronsIds()) {
                //计算出资质
                long qualification = countQualification(data, patronsId);
                result.put(patronsId, qualification);
            }
        }
        return result;
    }

    /**
     * 计算门客资质加成
     * @param data
     * @param patronsId
     * @return
     */
    private static long countQualification(ApprenticeUserPatronsTalentData data, int patronsId) {
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(patronsId);
        if (patronsInfo == null) {
            return 0;
        }
        //计算配置
        int pointConvert = GameConfig.APPRENTICE_APPOINT_CAREER_CONVERT;
        int noPointConvert = GameConfig.APPRENTICE_NO_APPOINT_CAREER_CONVERT;
        int convertMax = GameConfig.APPRENTICE_CONVERT_MAX;

        long qualification = 0;
        //士
        int convertNum1 = noPointConvert;
        if (patronsInfo.getOccupation() == eOccupationType.Scholar.getValue()) {
            convertNum1 = pointConvert;
        }
        qualification += data.getTalent1() / convertNum1;
        //农
        int convertNum2 = noPointConvert;
        if (patronsInfo.getOccupation() == eOccupationType.Farmer.getValue()) {
            convertNum2 = pointConvert;
        }
        qualification += data.getTalent2() / convertNum2;
        //工
        int convertNum3 = noPointConvert;
        if (patronsInfo.getOccupation() == eOccupationType.Craftsman.getValue()) {
            convertNum3 = pointConvert;
        }
        qualification += data.getTalent3() / convertNum3;
        //商
        int convertNum4 = noPointConvert;
        if (patronsInfo.getOccupation() == eOccupationType.Businessman.getValue()) {
            convertNum4 = pointConvert;
        }
        qualification += data.getTalent4() / convertNum4;
        //侠
        int convertNum5 = noPointConvert;
        if (patronsInfo.getOccupation() == eOccupationType.Knight.getValue()) {
            convertNum5 = pointConvert;
        }
        qualification += data.getTalent5() / convertNum5;
        //最大值判断
        return qualification > convertMax ? convertMax : qualification;
    }

    /**
     * 数值测试
     * @param num
     * @return
     */
    public static void test(int num) {
        ApprenticeConfig config = null;
        for (ApprenticeConfig item : configMap.values()) {
            config = item;
        }
        if (config == null) {
            return;
        }
        String resultStr = "";
        for (int level = 1; level <= 50; level++) {
            //k：类型，v：分数
            Map<Integer, TestData2> typeScoreMap = new HashMap<>();
            typeScoreMap.put(1, new TestData2(1));
            typeScoreMap.put(2, new TestData2(2));
            typeScoreMap.put(3, new TestData2(3));
            for (TestData2 data2 : typeScoreMap.values()) {
                //每个等级跑num次
                for (int i = 0; i < num; i++) {
                    TestData data = testDoOneLevel(level, data2);
                    data2.addScore(data.getScore());
                }
            }
            String str = "";
            for (TestData2 data2 : typeScoreMap.values()) {
                str += "type：" + data2.getType() + "，分数：" + data2.getScore() / data2.getNum() + "。";
            }
            resultStr += "等级：" + level + "。 " + str + "\r\n";
        }
        System.out.println(resultStr);
    }

    /**
     * 数值测试
     * @param level
     * @return
     */
    public static TestData testDoOneLevel(int level, TestData2 data2) {
        int type = data2.getType();
        int round = data2.getNum();
        long allTalent = data2.getScore();
        ApprenticeConfig config = null;
        for (ApprenticeConfig item : configMap.values()) {
            config = item;
        }
        if (config == null) {
            return null;
        }
        //1：无特殊，2：单特殊，3：双特殊
        int sTypeNum;
        if (type == 1) {
            sTypeNum = 0;
        } else if (type == 2) {
            sTypeNum = 1;
        } else {
            sTypeNum = 2;
        }

        ApprenticeLevelConfig levelConfig = config.getLevelConfig(level);
        String excludeProjectIdStr = "10026,10027,10028,10029,10030,10031,10032,10033,10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,10049";
        Set<Integer> excludeProjectIds = StringUtils.stringToSet(excludeProjectIdStr, ",");
        List<Integer> occProjectIdList = config.randomProjectIdsByLevel(level, levelConfig.getChooseNum() - sTypeNum, excludeProjectIds, new HashSet<>(), new HashSet<>(), false);
        List<ApprenticeProjectConfig> occProjectList = new ArrayList<>();
        for (int occProjectId : occProjectIdList) {
            occProjectList.add(config.getProjectConfig(occProjectId));
        }
        //优先品质高的
        List<ApprenticeProjectConfig> selectProjectList = new ArrayList<>();
        occProjectList.sort(Comparator.comparing(ApprenticeProjectConfig::getSort).reversed());
        //选择
        int selectNum = 0;
        int canSelectNum = levelConfig.getProjectNum() - sTypeNum;
        for (ApprenticeProjectConfig projectConfig : occProjectList) {
            if (selectNum >= canSelectNum) {
                break;
            }
            selectProjectList.add(projectConfig);
            selectNum++;
        }
        //加分数
        long score = 0;
        for (ApprenticeProjectConfig projectConfig : selectProjectList) {
            String[] scoreParam = projectConfig.getScore().split("\\|");
            int addScore = Integer.parseInt(scoreParam[1]);
            score += addScore;
        }
        TestData data = new TestData();
        data.setType(type);
        data.setScore(score);
        return data;
    }

    static class TestData {
        private int type;
        private long score;

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public long getScore() {
            return score;
        }

        public void setScore(long score) {
            this.score = score;
        }
    }

    static class TestData2 {
        private int type;
        private int num;
        private long score;

        public TestData2(int type) {
            this.type = type;
            this.num = 0;
            this.score = 0;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public int getNum() {
            return num;
        }

        public void setNum(int num) {
            this.num = num;
        }

        public long getScore() {
            return score;
        }

        public void setScore(long score) {
            this.score = score;
        }

        public void addScore(long addScore) {
            this.num++;
            this.score += addScore;
        }
    }
}
